home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cocktail / doc.lha / doc.doc / trafo.doc < prev    next >
Text File  |  1992-09-25  |  59KB  |  1,469 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11. ___________________________________________________________________
  12.  
  13.                                    Transformation
  14.                                    of Attributed Trees
  15.                                    Using Pattern Matching
  16.  
  17.                                    J. Grosch
  18.  
  19.  
  20. ___________________________________________________________________
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  
  50. ___________________________________________________________________
  51.                                    GESELLSCHAFT FUeR MATHEMATIK
  52.                                    UND DATENVERARBEITUNG MBH
  53.  
  54.                                    FORSCHUNGSSTELLE FUeR
  55.                                    PROGRAMMSTRUKTUREN
  56.                                    AN DER UNIVERSITAeT KARLSRUHE
  57. ___________________________________________________________________
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73.  
  74.  
  75.                                    Project
  76.  
  77.                              Compiler Generation
  78.  
  79.          ___________________________________________________________
  80.  
  81.           Transformation of Attributed Trees Using Pattern Matching
  82.  
  83.  
  84.                                  Josef Grosch
  85.  
  86.  
  87.                                 Aug. 28, 1991
  88.  
  89.          ___________________________________________________________
  90.  
  91.  
  92.                                 Report No. 27
  93.  
  94.  
  95.                              Copyright c 1991 GMD
  96.  
  97.  
  98.             Gesellschaft fuer Mathematik und Datenverarbeitung mbH
  99.                 Forschungsstelle an der Universitaet Karlsruhe
  100.                           Vincenz-Priesznitz-Str. 1
  101.                                D-7500 Karlsruhe
  102.  
  103.  
  104.  
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122.  
  123.  
  124.  
  125.  
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.                                                                              1
  135.  
  136.  
  137.           Transformation of Attributed Trees Using Pattern Matching
  138.  
  139.  
  140.                                  Josef Grosch
  141.               GMD Forschungsstelle an der Universitaet Karlsruhe
  142.              Vincenz-Priesznitz-Str. 1, D-7500 Karlsruhe, Germany
  143.                                  +721-662226
  144.                            grosch@karlsruhe.gmd.de
  145.  
  146.  
  147.  
  148. Abstract   This paper describes a tool for the  transformation  of  attributed
  149. trees using pattern matching.  The trees to be processed are defined by a for-
  150. malism based on context-free grammars.  Operations for trees such as  composi-
  151. tion  and decomposition are provided.  The approach can be characterized as an
  152. amalgamation of trees or terms including  pattern  matching,  with  recursion,
  153. attribute  grammars,  and  imperative programming.  Transformations can either
  154. modify the input trees or map them to arbitrary output.  Possible applications
  155. are  the  various transformation tasks in compilers such as semantic analysis,
  156. optimization, or the generation of intermediate representations.   The  design
  157. goals  have  been  to  combine  an  expressive  and  high  level technique for
  158. transformation with flexibility, efficiency, and practical usability.  A reli-
  159. able development style is supported by static typing and checks for the single
  160. assignment property of variables.  We give some  example  transformations  and
  161. describe  the  input  language  of  our tool called puma.  The relationship to
  162. similar work is discussed.  Finally, experimental results are  presented  that
  163. demonstrate the efficiency of our approach.
  164.  
  165. Keywords   transformation, attributed trees, pattern matching
  166.  
  167. 1.  Introduction
  168.  
  169. The transformation of trees using pattern matching becomes an  accepted  tech-
  170. nique.   Several tools have been constructed recently that follow this princi-
  171. ple [CoP90, HeS91, LMW89, Vol91].  Tools for code generation successfully  use
  172. the  same technique, too [AGT89, ESL89]. We present a new tool called puma and
  173. its input language for the transformation and manipulation of attributed trees
  174. and  graphs  [Gro91a].  Puma stands for pattern matching and unification.  Its
  175. intended application areas are the various transformation tasks in a  compiler
  176. operating  on  abstract  syntax  trees  or  arbitrary  graph  structures. This
  177. includes  semantic  analysis,  optimization,  intermediate  code   generation,
  178. source-to-source translation, and eventually machine code generation.
  179.  
  180.      The trees that are subject to pattern matching are described by a formal-
  181. ism  based  on  context-free  grammars.  The tree nodes may be associated with
  182. attributes of arbitrary types.  Node types are used to specify the  properties
  183. of  tree  nodes.  An  extension mechanism induces a subtype relation among the
  184. node types. Pattern matching is extended to handle  subtypes  and  attributes,
  185. too.  Operations  for the composition and decomposition of trees are supported
  186. by a concise notation.
  187.  
  188.      The building blocks for a transformation are recursive subroutines, clas-
  189. sified  as  procedures, functions, and predicates, with an arbitrary number of
  190.  
  191.  
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.                                                                              2
  201.  
  202.  
  203. input and output parameters. The bodies of the subroutines  consist  of  rules
  204. which  are  made up of patterns, conditions, statements, and expressions.  The
  205. first two components control the applicability  of  a  rule.   The  statements
  206. determine  what has to be done whenever a rule is applicable.  The expressions
  207. provide values for the output parameters and the function result.
  208.  
  209.      Static type checking with respect to trees  is  provided.  Variables  are
  210. declared  implicitly  and they are checked for the single assignment property.
  211. There is read and write access to attributes stored in the tree  which  allows
  212. the  construction  of  attribute  evaluators.  In all places it is possible to
  213. escape to hand-written code which provides the power and  flexibility  of  the
  214. imperative programming style.
  215.  
  216.      The output of the generator is a source  module  in  one  of  the  target
  217. languages C or Modula-2.  This module allows for easy integration and coopera-
  218. tion with other modules, either hand-written or generated ones.   The  pattern
  219. matching  is  local  and considers a region at the top of the current subtree,
  220. only.  It is implemented by direct code and therefore efficient.
  221.  
  222.      Our approach can be regarded from several points of view: From the  point
  223. of  view  of  imperative  programming  it is an extension by statically typed,
  224. attributed trees, constructs for composition and  decomposition,  and  pattern
  225. matching.   From  the point of view of logic programming it omits backtracking
  226. and restricts pattern matching to one of the two terms being  a  ground  term.
  227. It adds attributes which are stored in the terms (trees), static typing, input
  228. and output modes for parameters, and an easy escape  to  imperative  features.
  229. From the point of view of functional programming it offers the simple style of
  230. functional programming which has always been present in  imperative  languages
  231. having  functions  and recursion. It adds the pattern matching facility.  From
  232. the point of view of attribute grammars it allows the specification of  attri-
  233. bute  evaluation  with  explicit  control  of  the  evaluation  order or visit
  234. sequences. This eases the use of global attributes and gives full  control  on
  235. side-effects.
  236.  
  237.      The intended use of this tool proceeds in three steps: First, a  tree  is
  238. constructed  either  by a parser, a previous transformation phase, or whatever
  239. is appropriate.  Second, the attributes in the tree are evaluated either using
  240. an attribute grammar based tool, by a puma specified tree traversal and attri-
  241. bute computations, or by hand-written code.  Third,  the  attributed  tree  is
  242. transformed  or mapped to another data structure by a puma generated transfor-
  243. mation module.  These steps can be executed one after the  other  or  more  or
  244. less  simultaneously.   Besides  trees,  puma  can handle attributed graphs as
  245. well, even cyclic ones. Of course the cycles have to be detected in  order  to
  246. avoid  infinite  loops. A possible solution uses attributes as marks for nodes
  247. already visited.
  248.  
  249.      A transformer module can make use of attributes in the following ways: If
  250. attribute values have been computed by a preceding attribute evaluator and are
  251. accessed in read only mode then this  corresponds  to  the  three  step  model
  252. explained  above.  A puma generated module can also evaluate attributes on its
  253. own. A further possibility is that an attribute evaluator can call  puma  sub-
  254. routines  in  order to compute attributes. This is especially of interest when
  255. attributes depend on tree-valued arguments.
  256.  
  257.  
  258.  
  259.  
  260.  
  261.  
  262.  
  263.  
  264.  
  265.  
  266.                                                                              3
  267.  
  268.  
  269.      The tool supports two  classes  of  tree  transformations:  mappings  and
  270. modifications.  Tree mappings map an input tree to arbitrary output data.  The
  271. input tree is accessed in read only mode and left  unchanged.  Tree  modifica-
  272. tions change a tree by e. g. computing and storing attributes at tree nodes or
  273. by changing the tree structure. In this case the tree data structure serves as
  274. input as well as output and it is accessed in read and write mode.
  275.  
  276.      The first class covers applications like the generation  of  intermediate
  277. languages  or  machine  code. Trees are mapped to arbitrary output like source
  278. code, assembly code, binary machine code,  linearized  intermediate  languages
  279. like  P-Code,  or  another  tree structure. A further variant of mapping is to
  280. emit a sequence of procedure calls which are handled by an abstract data type.
  281.  
  282.      The second class covers applications like semantic analysis or  optimiza-
  283. tion.  Trees  are  decorated  with  attribute  values, properties of the trees
  284. corresponding to context conditions are checked, or trees are changed in order
  285. to reflect optimizing transformations.
  286.  
  287.      Puma is part of the Karlsruhe Toolbox for Compiler Construction  [GrE90].
  288. In  particular  it cooperates with the generator for abstract syntax trees ast
  289. [Gro91b] and the attribute evaluator  generator  ag  [Gro89].  The  attributed
  290. trees are defined and managed by a module generated with ast.  A second module
  291. generated by puma creates and handles these trees.  This way all the  powerful
  292. operations  for  trees and graphs provided by ast are available such as reader
  293. and writer procedures or the interactive browser.  For sake of  simplicity  we
  294. will  deviate  from reality in this paper and treat the definition of the tree
  295. structure as part of puma.
  296.  
  297.      The rest of this paper is organized as follows: Section 2 presents a  few
  298. simple  examples  of  how  to  describe  transformations with puma.  Section 3
  299. describes the input language of the tool.  Section 4 sketches the  implementa-
  300. tion  of  the  generated  transformer module.  Section 5 compares our approach
  301. with related work.  Section 6 presents experimental results.  Section  7  con-
  302. tains concluding remarks.
  303.  
  304. 2.  Tree Transformation by Pattern Matching
  305.  
  306. The probably easiest way to get an impression of our approach can be  obtained
  307. by having a look at a few introductory examples. We will use the abstract syn-
  308. tax of simple arithmetic expressions as input data structure.  Besides  a  few
  309. intrinsic attributes describing e. g. the values of constants we use an attri-
  310. bute called Type.  It describes the type of every  subexpression.  Its  domain
  311. are  trees, too.  The tree definition based on a context-free grammar shown in
  312. Example 1 specifies the structure of expressions and types.
  313.  
  314.  
  315.  
  316.  
  317.  
  318.  
  319.  
  320.  
  321.  
  322.  
  323.  
  324.  
  325.  
  326.  
  327.  
  328.  
  329.  
  330.  
  331.                                                                              4
  332.  
  333.  
  334.     Example 1: Tree Definition
  335.     Expr            = Type <
  336.        Plus         = Lop: Expr Rop: Expr .
  337.        Minus        = Lop: Expr Rop: Expr .
  338.        Const        = [Value] .
  339.        Adr          = <
  340.           Index     = Adr Expr .
  341.           Select    = Adr [Ident: tIdent] .
  342.           Ident     = [Ident: tIdent] .
  343.        >.
  344.     >.
  345.     Type            = <
  346.        Int          = .
  347.        Real         = .
  348.        Bool         = .
  349.        Array        = [Lwb] [Upb] Type .
  350.        Record       = Fields .
  351.     >.
  352.     Fields          = <
  353.        NoField      = .
  354.        Field        = [Ident: tIdent] Type Fields .
  355.     >.
  356.  
  357.  
  358.      The names before the character '=' can be regarded both as rule names  or
  359. nonterminals.   The possible right-hand sides for one nonterminal are enclosed
  360. in angle brackets '<' and '>'.  Non-tree valued  attributes  are  enclosed  in
  361. square  brackets  '['  and ']'.  The attributes Lwb, Upb, and Value are of the
  362. default type int.  The attribute Ident is of  the  user-defined  type  tIdent.
  363. The  tree-valued  attribute  Type of the rule named Expr is written like every
  364. other right-hand side nonterminal.  The selector names Lop and Rop used in the
  365. rules  called Plus and Minus allow symbolic access to right-hand side elements
  366. having the same type.
  367.  
  368.      The association of an attribute such as Type with a nonterminal like Expr
  369. adds  this  attribute  to every right-hand side belonging to this nonterminal.
  370. Hence the rules Plus and Minus have three right-hand side elements.
  371.  
  372.      The subroutine specification presented in Example 2 describes part  of  a
  373. transformation  of  expression  trees  to P-Code [NAJ76]. The procedure P_Code
  374. performs a recursive tree traversal. Its body consists of a sequence of rules.
  375. Every rule is made up of a pattern and a list of statements separated by ':-'.
  376. Whenever a pattern matches against the input parameter of the subroutine,  the
  377.  
  378.     Example 2: Generation of P-Code
  379.     PROCEDURE P_Code (Tree)
  380.     Plus  (Int  (), Lop, Rop) :- P_Code (Lop); P_Code (Rop); Emit (ADDI); .
  381.     Plus  (Real (), Lop, Rop) :- P_Code (Lop); P_Code (Rop); Emit (ADDR); .
  382.     Minus (Int  (), Lop, Rop) :- P_Code (Lop); P_Code (Rop); Emit (SUBI); .
  383.     Minus (Real (), Lop, Rop) :- P_Code (Lop); P_Code (Rop); Emit (SUBR); .
  384.  
  385.  
  386.  
  387.  
  388.  
  389.  
  390.  
  391.  
  392.  
  393.  
  394.  
  395.                                                                              5
  396.  
  397.  
  398. associated statement list is executed. The parameter of the  procedure  P_Code
  399. is  of  type Tree which means that every tree according to the tree definition
  400. is a legal argument. The procedure Emit is supposed to be an external  subrou-
  401. tine that performs output.
  402.  
  403.     Example 3: Computation of Type Sizes
  404.     FUNCTION TypeSize ([Type, Fields]) int
  405.     Int  ()              RETURN 4 .
  406.     Real ()              RETURN 4 .
  407.     Bool ()              RETURN 1 .
  408.     Array (Lwb, Upb, T)  RETURN (Upb - Lwb + 1) * TypeSize (T) .
  409.     Record (F)           RETURN TypeSize (F) .
  410.     Field (_, T, F)      RETURN TypeSize (T) + TypeSize (F) .
  411.     NoField ()           RETURN 0 .
  412.  
  413.  
  414.      The function TypeSize in Example 3 transforms or maps  trees  to  integer
  415. values.  It  is  defined  to  operate on trees of types Type and Fields and it
  416. returns a value of a type named int.  Again this subroutine performs a  recur-
  417. sive  tree  traversal. Instead of producing a side-effect like in the previous
  418. example it represents a pure functional mapping and  demonstrates  the  arith-
  419. metic  expression capabilities of puma.  The character '_' denotes a so-called
  420. don't care pattern.
  421.  
  422.     Example 4: Testing two Types for Compatibility
  423.     PREDICATE IsCompatible ([Type, Fields], [Type, Fields])
  424.     Int  ()             , Int  ()              .
  425.     Real ()             , Real ()              .
  426.     Bool ()             , Bool ()              .
  427.     Array (Lwb, Upb, T1), Array (Lwb, Upb, T2) :- IsCompatible (T1, T2); .
  428.     Record (F1)         , Record (F2)          :- IsCompatible (F1, F2); .
  429.     Field (_, T1, F1)   , Field (_, T2, F2)    :- IsCompatible (T1, T2);
  430.                                                   IsCompatible (F1, F2); .
  431.  
  432.  
  433.      Example 4 presents the predicate IsCompatible which  can  be  seen  as  a
  434. boolean  function.  It  operates  on  two  parameters of types Type or Fields.
  435. Accordingly, every rule has two patterns for matching against  the  two  argu-
  436. ments.   The first three rules lead to a return value of true if both patterns
  437. match both arguments.  The fourth rule returns true if the attributes Lwb  and
  438. Upb of the two argument trees match (have the same value) and if the recursive
  439. call IsCompatible returns true for the two types T1 and T2 of the  array  ele-
  440. ments. If none of the rules matches the predicate returns false.
  441.  
  442.      The subroutine given in Example 5 has three input and one output  parame-
  443. ter.  It  computes the result type of a binary expression which depends on the
  444. types of the operands and on the operator. The third pattern of every rule  is
  445. enclosed  in  curly brackets '{ and '}'. This represents so-called target code
  446. which is more or less passed unchanged and unchecked to the generated  module.
  447. In  this  case  opPlus  and  opMinus  are  named constants encoding operators.
  448. Without the curly brackets they would be treated  as  pattern  variables.  The
  449.  
  450.  
  451.  
  452.  
  453.  
  454.  
  455.  
  456.  
  457.  
  458.  
  459.                                                                              6
  460.  
  461.  
  462.  
  463.     Example 5: Procedure with Input and Output Parameters
  464.     PROCEDURE ResultType (Type, Type, Operator: int => Type)
  465.     Int  () , Int  () , { opPlus  } => Int  () .
  466.     Real () , Real () , { opPlus  } => Real () .
  467.     Int  () , Int  () , { opMinus } => Int  () .
  468.     Real () , Real () , { opMinus } => Real () .
  469.  
  470. expression after the symbol '=>' describes the value of the  output  parameter
  471. in case of a successful match. It consists of a tree constructor which creates
  472. a tree having one node.
  473.  
  474. 3.  Specification Language
  475.  
  476. The description of a tree transformation consists of the definition of  attri-
  477. buted trees and a set of subroutines.
  478.  
  479. 3.1.  Tree Structure
  480.  
  481. The structure of attributed trees or (directed) graphs is specified by a  for-
  482. malism based on context-free grammars. However, we primarily use the terminol-
  483. ogy of trees and types, here. A tree consists of nodes.  A node may be related
  484. to  other  nodes  in a so-called parent-child relation. Then the first node is
  485. called a parent node and the  latter  nodes  are  called  child  nodes.  Nodes
  486. without  a  parent  node are usually called root nodes, nodes without children
  487. are called leaf nodes.
  488.  
  489.      The structure and the properties of nodes are described  by  node  types.
  490. Every node belongs to a node type.  A specification of a tree describes a fin-
  491. ite number of node types.  A node type specifies the names of the child  nodes
  492. and  the  associated node types as well as the names of the attributes and the
  493. associated attribute types.
  494.  
  495.      Children are distinguished by selector names which have to be unambiguous
  496. within one node type.  The children are of a certain node type. Example:
  497.  
  498.        Plus      = Lop: Expr Rop: Expr .
  499.        Index     = Adr: Adr Expr: Expr .
  500.  
  501. The example introduces two node types called Plus and Index.  A node  of  type
  502. Plus has two children which are selected by the names Lop and Rop.  Both chil-
  503. dren are of the node type Expr.  If a selector name is equal to the associated
  504. name of the node type it can be omitted. Therefore, the node type Index can be
  505. abbreviated as follows:
  506.  
  507.        Index     = Adr Expr .
  508.  
  509.  
  510.      As well as children, every node type can specify an arbitrary  number  of
  511. attributes  of arbitrary types. Like children, attributes are characterized by
  512. a selector name and a  certain  type.   The  descriptions  of  attributes  are
  513. enclosed in brackets '[' and ']'. The attribute types are given by names taken
  514.  
  515.  
  516.  
  517.  
  518.  
  519.  
  520.  
  521.  
  522.  
  523.  
  524.                                                                              7
  525.  
  526.  
  527. from the target language. Missing attribute types are assumed  to  be  int  or
  528. INTEGER depending on the target language (C or Modula-2).  Children and attri-
  529. butes can be given in any order (see Example 1).
  530.  
  531.      To allow several alternatives for the  types  of  children  an  extension
  532. mechanism is used. A node type may be associated with several other node types
  533. enclosed in angle brackets '<' and '>'. Then this node type is called base  or
  534. super  type  and the associated types are called derived types or subtypes.  A
  535. derived type can in turn be extended with no limitation of the nesting  depth.
  536. The  extension mechanism induces a subtype relation between node types denoted
  537. by the symbol  . This relation is transitive.  Where a node of a certain  node
  538. type  is  required,  either  a  node  of this node type or a node of a subtype
  539. thereof is legal.
  540.  
  541.      In Example 1 Expr is a base type describing nodes with one  child  called
  542. Type.   The  node  type Expr has four derived types called Plus, Minus, Const,
  543. and Adr.  The node type Adr is in turn extended by three derived types  called
  544. Index,  Select,  and  Ident.   Where a node of type Expr is required, all men-
  545. tioned node types are legal.  Where a node of type Adr is required,  nodes  of
  546. the  types  Index,  Select, or Ident are legal.  Where a node of type Index is
  547. required, nodes of type Index are legal, only. The  subtype  relation  is  the
  548. transitive and reflexive closure of: Plus  Expr, Minus  Expr, Const  Expr, Adr
  549.  Expr, Index  Adr, Select  Adr, Ident  Adr.
  550.  
  551.      Besides extending the set of legal node types,  the  extension  mechanism
  552. has  the  property  of extending the children and attributes of the base type.
  553. The derived types possess the children and attributes of the base type.   They
  554. may define additional children and attributes. In other words they inherit the
  555. structure of the base type.  The selector names of all children and attributes
  556. in  an  extension hierarchy have to be distinct.  The syntax has been designed
  557. this way in order to allow single inheritance, only.
  558.  
  559.      In Example 1 nodes of type Expr have one child selected by the name Type.
  560. Nodes  of type Plus have three children with the selector names Type, Lop, and
  561. Rop.
  562.  
  563. 3.2.  Subroutines
  564.  
  565. A set of subroutines constitutes the main building blocks of a transformation.
  566. Like  in  programming languages, subroutines are parameterized abstractions of
  567. statements or expressions.  There are three kinds of subroutines:
  568.  
  569.     procedure: a subroutine acting as a statement
  570.     function: a subroutine acting as an expression and returning a value
  571.     predicate: a boolean function
  572.  
  573. Subroutines are specified according to the following syntax:
  574.  
  575.  
  576.  
  577.  
  578.  
  579.  
  580.  
  581.  
  582.  
  583.  
  584.  
  585.  
  586.  
  587.  
  588.  
  589.                                                                              8
  590.  
  591.  
  592.     Subroutine = Header { Rule }
  593.     Header     = PROCEDURE Ident ( [ Parameters ] [ => Parameters ] )
  594.                | FUNCTION  Ident ( [ Parameters ] [ => Parameters ] ) Type
  595.                | PREDICATE Ident ( [ Parameters ] [ => Parameters ] )
  596.     Parameters = [ Ident : ] Type { , [ Ident : ] Type }
  597.  
  598.  
  599. A subroutine consists of a header and a sequence of rules.  The header  speci-
  600. fies  the  kind  of the subroutine, its name, and its parameters. In case of a
  601. function, the type of the result value is added. Input and  output  parameters
  602. are  separated  by the symbol '=>'.  It suffices to give the type of a parame-
  603. ter. A name for the formal parameter is optional.
  604.  
  605. 3.3.  Types
  606.  
  607. Types are either predefined in the target language like int  and  INTEGER,  or
  608. user-defined  like  MyType,  or they are tree types like Expr.  A tree type is
  609. described by the name of a tree definition, a single node type, or a  list  of
  610. node types enclosed in brackets '[' and ']'. In case of ambiguities the latter
  611. two kinds may be qualified by preceding the name of the tree definition.
  612.  
  613.     Type     = TreeType | UserType
  614.     TreeType = Ident | [ Ident . ] Ident | [ Ident . ] '[' Idents ']'
  615.     UserType = Ident
  616.     Idents   = Ident { , Ident }
  617.  
  618.  
  619. 3.4.  Rules
  620.  
  621. A rule behaves like a branch in a case or switch statement. It consists  of  a
  622. list  of  patterns,  a  list  of expressions, a return expression in case of a
  623. function, and a list of statements.
  624.  
  625.     Rule     = [ Patterns ] [ => Exprs ] [ RETURN Expr ] :- { Statement ; } .
  626.     Patterns = Pattern { , Pattern }
  627.     Exprs    = Expr { , Expr }
  628.  
  629.  
  630.      The semantics of a rule is as follows: A rule may succeed  or  fail.   It
  631. succeeds  if all its patterns, statements, and expressions succeed - otherwise
  632. it fails. The patterns, statements, and expressions are checked for success in
  633. the  following  order:  First,  the patterns are checked from left to right. A
  634. pattern succeeds if it matches its corresponding input parameter as  described
  635. below.   Second,  the  statements  are  executed  in  sequence as long as they
  636. succeed.  The success of statements is defined below.  Third, the  expressions
  637. are  evaluated  from  left  to  right  and  their  results  are  passed to the
  638. corresponding output parameters.  In case  of  a  function,  additionally  the
  639. expression  after  RETURN  is evaluated and its result is returned as value of
  640. the function call.  The success of expressions is defined below, too.  If  all
  641. elements  of a rule succeed then the rule succeeds and the subroutine returns.
  642. If one element of a rule fails the process described above  stops  and  causes
  643. the  rule to fail. Then the next rule is tried.  This search process continues
  644. until either a successful rule is found or the end of the list is reached.  In
  645.  
  646.  
  647.  
  648.  
  649.  
  650.  
  651.  
  652.  
  653.  
  654.  
  655.                                                                              9
  656.  
  657.  
  658. the  latter  case  the behaviour depends on the kind of the subroutine: A pro-
  659. cedure does nothing, a predicate returns false, and a function signals a  run-
  660. time  error.  There is one exception to this definition of the semantics which
  661. is explained later.
  662.  
  663. 3.5.  Patterns
  664.  
  665. A pattern describes the shape at the top or root of a subtree.  A pattern  can
  666. be  a  decomposition of a tree, the keyword NIL, a label or a variable, one of
  667. the don't care symbols '_' or '..', or an expression. A decomposition is writ-
  668. ten  as a node type followed by a list of patterns in parenthesis '(' and ')'.
  669. It may be optionally preceded by a label.
  670.  
  671. Pattern = [ Ident : ] Ident ( [ Patterns ] ) | NIL | Ident | _ | .. | Expr
  672.  
  673.  
  674. The match between a pattern and a value is defined  recursively  depending  on
  675. the kind of the pattern:
  676.  
  677.      A decomposition with a node type t matches a tree u with a root  node  of
  678. type  s  if  s  is  a subtype of t (s  t) and all subpatterns of t match their
  679. corresponding subtrees or attributes of u.  If the node type is preceded by  a
  680. label  l then a binding is established between l and u which defines the label
  681. l to refer to the tree u.
  682.  
  683.      The first occurrence of a label l in a rule matches an arbitrary  subtree
  684. or  attribute value u.  All further occurrences of the label l within patterns
  685. of this rule match a subtree or an attribute value v only if u is equal to  v.
  686. The equality for trees is defined in the sense of structural equivalence.  Two
  687. attributes are equal if they have the same values.  A binding  is  established
  688. between  l and u which defines the label l to refer to the value u.  The label
  689. can be used later to access the associated value.
  690.  
  691.      The pattern NIL matches the values NULL or NIL.  The  don't  care  symbol
  692. '_'  matches  one arbitrary subtree or attribute value.  The don't care symbol
  693. '..' matches any number of arbitrary subtrees or attribute values.  An expres-
  694. sion matches a parameter or an attribute if both have the same values.
  695.  
  696. 3.6.  Expressions
  697.  
  698. Expressions denote the computation of values or  the  construction  of  trees.
  699. Binary and unary operations as well as calls of external functions are written
  700. as in the target language. Calls of puma functions and predicates  distinguish
  701. between  input and output arguments.  The syntax for tree composition is simi-
  702. lar to the syntax of patterns.
  703.  
  704.     Expr = Ident ( [ Exprs ] ) | NIL | Ident | _ | ..
  705.          | Ident ( [ Exprs ] [ => Patterns ] )
  706.  
  707.  
  708. The semantics of the different kinds of expressions is as follows:
  709.  
  710.  
  711.  
  712.  
  713.  
  714.  
  715.  
  716.  
  717.  
  718.  
  719.  
  720.                                                                             10
  721.  
  722.  
  723.      A node type creates a tree node and provides the children and  attributes
  724. of  this  node with the values given in parenthesis.  NIL represents the value
  725. NULL or NIL.  A label refers to the expression it was bound to upon its defin-
  726. ition.
  727.  
  728.      A function or predicate call must be compatible  with  the  corresponding
  729. definition  in  terms  of  the  numbers of expressions and patterns as well as
  730. their types.  A function call evaluates the expressions corresponding to input
  731. parameters,  passes  the  results  to the function, and executes the function.
  732. Upon return from the function the result value of the function determines  the
  733. result of this expression.  The values of the output parameters that the func-
  734. tion returns are matched against the actual patterns of the function call.  If
  735. one  pair does not match the call fails.  Labels in the patterns may establish
  736. bindings that enable to refer to the output parameters or subtrees thereof.
  737.  
  738.      The don't care symbols specify that no computation  should  be  executed,
  739. either  for  one  or for several expressions. The result values are undefined.
  740. The binary and unary operators (prefix and postfix) of the target language  as
  741. well  as  array indexing, parentheses, numbers, and strings are known to puma.
  742. They are passed unchanged to the output.
  743.  
  744.      In case of node types, labels for tree values,  and  functions  returning
  745. tree values, puma does type checking. For user types, target code expressions,
  746. or target operators no type checking is done by puma but  later  by  the  com-
  747. piler.  An  expression that does not contain calls of puma functions or predi-
  748. cates always succeeds. An expression containing those calls  succeeds  if  all
  749. the calls succeed - otherwise it fails.
  750.  
  751. 3.7.  Statements
  752.  
  753. Statements are used to describe  conditions,  to  perform  output,  to  assign
  754. values  to  attributes,  and  to  control the execution of the transformer via
  755. recursive subroutine calls. A statement is either a condition  denoted  by  an
  756. expression,  a  call of a procedure, an assignment, one of the keywords REJECT
  757. or FAIL, or a target code statement. Every kind of statement  may  succeed  or
  758. fail as described below.
  759.  
  760.     Statement    = Expr | Ident ( [ Exprs ] [ => Patterns ] ) | Ident := Expr
  761.                  | REJECT | FAIL | [ Declarations ] TargetCode
  762.     Declarations = Parameters
  763.  
  764.  
  765.      Conditions are denoted by expressions and can be used to  determine  pro-
  766. perties  that  can  not  be  expressed  with  pattern matching alone. Patterns
  767. describe either shapes of a fixed size of a tree or the equality  between  two
  768. values.  Properties  of  trees  of unlimited size and relations like '<', '<='
  769. etc. have to be checked with conditions.  The expression has  to  be  of  type
  770. boolean  or  the  call of a predicate.  A condition succeeds if the expression
  771. evaluates to true - otherwise it fails.
  772.  
  773.      For a procedure call the same rules as for a  function  call  apply.   It
  774. succeeds if the values of all output parameters are matched by the correspond-
  775. ing patterns - otherwise it fails.
  776.  
  777.  
  778.  
  779.  
  780.  
  781.  
  782.  
  783.  
  784.  
  785.  
  786.                                                                             11
  787.  
  788.  
  789.      An assignment statement evaluates its expression and stores this value at
  790. the entity denoted by the identifier on the left-hand side. The identifier can
  791. denote a global or a local variable, an input or an output parameter, as  well
  792. as a label for an attribute or a subtree.  An assignment statement succeeds if
  793. the expression succeeds - otherwise it fails.
  794.  
  795.      The statement REJECT does nothing but fail. This way the execution of the
  796. current rule terminates and control is passed to the next rule.  The statement
  797. FAIL causes the execution of the current subroutine to terminate. This  state-
  798. ment  is allowed in procedures and predicates, only.  Depending on the kind of
  799. subroutine the following happens:  A  procedure  terminates  and  a  predicate
  800. returns false.
  801.  
  802.      A target code statement which is enclosed in curly brackets '{'  and  '}'
  803. is  executed  as  in  the  target language. It can be used to define labels by
  804. means of implementation language code or calls  of  external  subroutines.  In
  805. this  case  the  names of the labels and their types have to be defined expli-
  806. citly. This is done by declarations written in the syntax of a parameter  list
  807. that  precede  the  target  code  statement.   A  target code statement always
  808. succeeds.
  809.  
  810.      Note, statements and expressions may cause side effects by changing e. g.
  811. global  variables,  local  variables,  the input tree, or by producing output.
  812. Those side effects are not undone when a rule fails.
  813.  
  814.      Further features such as various  possibilities  concerning  the  use  of
  815. hand-written  target  code,  named patterns instead of positional ones, or the
  816. definition of the equality or matching operation between attributes by a macro
  817. mechanism are omitted for the sake of brevity.
  818.  
  819. 4.  Implementation
  820.  
  821. From a given specification, puma generates a program module in one of the tar-
  822. get  languages C or Modula-2 implementing the desired transformation. The sub-
  823. routines in the sense  of  puma  are  mapped  to  subroutines  in  the  target
  824. language. Procedures yield procedures, functions yield functions that return a
  825. value, and predicates yield boolean functions. These subroutines can be called
  826. from  other  modules  using  the  usual  subroutine  call syntax of the target
  827. language provided they are exported: All arguments are separated by  commas  -
  828. the  symbol  '=>'  as  separator  between  input  and output arguments is only
  829. required in calls processed by puma.
  830.  
  831.      The types of the parameters are treated as follows: Predefined  types  or
  832. user  defined  types  remain  unchanged.  Node types or sets of node types are
  833. replaced by the name of the corresponding tree type.  This is a pointer  to  a
  834. union of record types. Input parameters are passed by value and output parame-
  835. ters are passed by reference.
  836.  
  837.      The rules of a subroutine are treated like a comfortable case  or  switch
  838. statement.   The  code generated for pattern matching is relatively simple.  A
  839. naive implementation would just use a sequence of if statements.  This kind of
  840. code  showed  to  be  already  rather efficient.  puma optimizes the code with
  841. respect to the elimination of common tests for patterns and the clever use  of
  842.  
  843.  
  844.  
  845.  
  846.  
  847.  
  848.  
  849.  
  850.  
  851.  
  852.                                                                             12
  853.  
  854.  
  855. switch  statements.  Furthermore, tail recursion can be turned into iteration.
  856. Labels are replaced by access paths to the associated values.   The  code  for
  857. the construction of tree nodes is inserted in-line.  It is therefore efficient
  858. because no procedure calls are necessary for the creation of tree nodes.
  859.  
  860. 5.  Related Research
  861.  
  862. In this section we compare our approach with several programming paradigms and
  863. similar  tools.   The intention is to provide further insight in the nature of
  864. our tool by looking at styles or work the reader might be familiar with.
  865.  
  866. 5.1.  Imperative Programming
  867.  
  868. Our approach can be regarded as an extension of imperative languages by a type
  869. constructor  for trees. Operations on trees for the composition and decomposi-
  870. tion are provided using a concise term notation.  The storage  management  for
  871. trees is completely automatic. Intermediate variables for output parameters of
  872. subroutines are declared implicitly and checked for the single assignment pro-
  873. perty. Pattern matching represents a comfortable kind of case or switch state-
  874. ment tailored towards processing of trees. This imperative view  is  reflected
  875. best by the implementation of the generator puma.  It can be seen as a prepro-
  876. cessor that provides attributed trees  and  pattern  matching  for  imperative
  877. languages.
  878.  
  879. 5.2.  Logic Programming
  880.  
  881. From the stand point of logic programming languages such as Prolog [ClM84] our
  882. approach  is relatively restricted and therefore one cannot classify puma as a
  883. logic programming language.  Puma has no backtracking, no logic variables, and
  884. nothing  like  assert  and retract. The unification is unidirectional and res-
  885. tricted to one of the two terms being a ground term.  Similar are  the  syntax
  886. and  the presence of predicates.  Puma retains the "imperative subset" of Pro-
  887. log. It turns out that this subset can be implemented efficiently and it  suf-
  888. fices to specify most of the transformation problems in compilers [Paa89].
  889.  
  890.      Compared to Prolog the following features have been added: Besides predi-
  891. cates there are procedures, functions, and customary expressions.  This allows
  892. for recursive functions and easy calls of puma subroutines  from  hand-written
  893. code.  Attributes  can  be  stored  in the tree and accessed in read and write
  894. mode. The terms or trees are statically typed. For parameters the modes  input
  895. and  output  are distinguished. Pattern matching is extended to cope with sub-
  896. types and attributes.  The modification  of  input  terms  is  possible.  Easy
  897. escape  to  hand-written code and cooperation with other modules, either hand-
  898. written or generated, gives great  flexibility  and  "imperative  power".  The
  899. transformer  modules  including  the pattern matching are translated to direct
  900. code and therefore efficient.
  901.  
  902. 5.3.  Functional Programming
  903.  
  904. Compared to modern functional programming languages such as Hope  [BMS80],  ML
  905. [Mil85],  or  Miranda [Tur85] our approach can of course not claim to be func-
  906. tional. There is nothing like under or over supply  of  functions  or  higher-
  907. order   functions.   It  just  supports  the  restricted  kind  of  functional
  908.  
  909.  
  910.  
  911.  
  912.  
  913.  
  914.  
  915.  
  916.  
  917.  
  918.                                                                             13
  919.  
  920.  
  921. programming that can be found in imperative  languages  having  functions  and
  922. recursion  like e. g. C or Pascal. Even the function results are restricted to
  923. simple data types and pointers. However, the latter allow functions to  return
  924. trees  and  graphs.  With  respect to the traditional functional language Lisp
  925. [MAE65] our approach might be worth to be  compared.   Whereas  Lisp  supports
  926. binary  trees  only, puma provides tree nodes with an arbitrary number of sub-
  927. trees and attributes.  Dynamic typing and binding have been replaced by  their
  928. static counterparts. The pattern matching facility has been added.
  929.  
  930. 5.4.  Attribute Grammars
  931.  
  932. Our technique is related to attribute grammars [Knu68, Knu71] in several ways.
  933. Compared  to  pure  attribute grammar processors such as [Gro89, JoP90, KHZ82]
  934. there are some restrictions. In pure attribute grammar systems  the  attribute
  935. computations  are  written  in a functional notation. Knowing the dependencies
  936. among the attributes allows  the  automatic  (implicit)  determination  of  an
  937. evaluation  order for the attributes (visit sequences). Furthermore it is pos-
  938. sible to check an attribute grammar for completeness and non-circularity.  Our
  939. approach  is  based  on  an explicit evaluation order using hand-written visit
  940. sequences.  Three kinds of data can be  regarded  as  attributes:  The  "real"
  941. attributes  stored  in the tree, the parameters of the subroutines, and global
  942. variables. This classification of the attributes is done by the user.  Whereas
  943. pure  attribute  grammars allow only computations local to a grammar rule, the
  944. pattern matching facility makes computations on larger tree regions  of  fixed
  945. size  feasible.  Considering  attributes  of the kind parameter and non-nested
  946. patterns only, our approach is similar to affix  grammars  [Kos71,  Kos77]  or
  947. extended  affix  grammars  [Wat74].   This holds from the syntactic as well as
  948. from the semantic point of view. A puma generated  module  can  contribute  to
  949. attribute evaluation in several ways: First, the evaluation can be carried out
  950. completely by a transformation module itself using one or more subroutines for
  951. traversing  the tree.  Second, puma subroutines can be called as external sub-
  952. routines from an attribute evaluator to compute attributes - especially  those
  953. depending  on  tree-valued  arguments.   The imperative or sequential style of
  954. puma allows simple control on side effects and easy  production  of  arbitrary
  955. output.
  956.  
  957. 5.5.  Optran
  958.  
  959. The transformation tool  Optran  [LMW89]  has  been  designed  for  optimizing
  960. transformations.  It  is  based  on an attribute grammar and modifies an input
  961. tree according to a given set of rules. A rule consists of a  pattern,  condi-
  962. tions, and action statements. The actions can replace the tree part matched by
  963. the pattern (where the unmatched subtrees might be  reused)  and  compute  new
  964. attribute  values.  Optran emphasizes the automatic reevaluation of attributes
  965. [LMO88] in order to arrive at attribute values consistent with  the  specified
  966. attribute  grammar.  As  the  goals  of  Optran are rather ambitious they pose
  967. several problems: In which order will the rules be applied and how to find the
  968. locations  in  the tree where a pattern matches? When will the reevaluation of
  969. attributes be carried out? The latter question is interesting because  in  the
  970. worst  case  it will be necessary to recompute many attributes in a large part
  971. of the tree and therefore consume a considerable amount of run time.
  972.  
  973.  
  974.  
  975.  
  976.  
  977.  
  978.  
  979.  
  980.  
  981.  
  982.  
  983.                                                                             14
  984.  
  985.  
  986.      Our technique groups rules into an arbitrary number of subroutines. Every
  987. routine  may perform pattern matching on an arbitrary number of trees supplied
  988. as arguments not just one.  We explicitly control  the  execution  order  thus
  989. gaining  an  efficient and detailed way to describe where and when what should
  990. happen.  Puma is not concerned with reevaluation of attributes. Besides modif-
  991. ication  of  the input tree it also allows for mappings that produce arbitrary
  992. output.
  993.  
  994. 5.6.  Trafola
  995.  
  996. The functional language Trafola-H [HeS91] was designed to be  a  specification
  997. language  for  program  transformations.  Besides  all  the features one would
  998. expect from a modern functional language it has powerful constructs  for  pat-
  999. tern  matching.  For  example pattern matching is extended to cope with tuples
  1000. and sequences.  This introduces nondeterminism which is  handled  using  back-
  1001. tracking.  The language is statically typed and offers type polymorphism. Pat-
  1002. tern matching is implemented by a table-driven bottom up tree automata or by a
  1003. backtracking  algorithm.  The functional constructs are usually implemented by
  1004. interpretation of an internal abstract machine.  Our approach does not aim  to
  1005. be functional but it retains the flexibility and efficiency of imperative pro-
  1006. gramming. Whereas the Trafola type constructor for sequences allows the  gram-
  1007. mar  for  legal  trees  to be written in extended BNF, puma supports pure BNF,
  1008. only. Both approaches allow so-called non linear  patterns  where  a  variable
  1009. occurs  more  than  once  in a pattern.  Puma has extended pattern matching to
  1010. handle subtypes.
  1011.  
  1012. 5.7.  Codegenerator-Generators
  1013.  
  1014. Tools for the generation of code  generators  such  as  Twig  [AGT89]  or  Beg
  1015. [ESL89] often use tree pattern matching, too. In addition to a pattern, a con-
  1016. dition, and an action a rule is associated with costs. Pattern  matching  usu-
  1017. ally  performs  a  global  match on the complete input tree in order to find a
  1018. complete cover of the tree where the sum of  all  participating  rules  is  of
  1019. minimal  cost.  Algorithms  based  on dynamic programming have proved to yield
  1020. satisfactory results. These tools  are  oriented  towards  code  selection  by
  1021. transforming a tree-like intermediate representation into machine code. There-
  1022. fore there is de facto only one subroutine with one tree-valued argument.  Beg
  1023. provides  support  for register allocation, has a fixed traversal scheme (post
  1024. order), and generates directly coded code-generators.   Twig  allows  for  the
  1025. modification  of  the input tree, supports arbitrary traversal strategies, and
  1026. generates table-driven code-generators.
  1027.  
  1028. 5.8.  Txl
  1029.  
  1030. The tree transformation tool txl [CaC91, CoP90] processes concrete syntax.  It
  1031. comprises  a  parser  and an unparser for input and output of trees and allows
  1032. the generation of source-to-source translators.  The  tree  transformation  is
  1033. described  by  a  set  of  rules  consisting  of a pattern, a condition, and a
  1034. replacement. Usually the user does not have to take care about  the  order  or
  1035. location  of rule applications. Rules are applied as long as there is one that
  1036. matches. Thereby the tree is modified. There are means to describe  which  set
  1037. of  rules  should  be applied to which subtrees. Patterns are not written in a
  1038. nested fashion but as strings containing nonterminals. The tool  parses  these
  1039.  
  1040.  
  1041.  
  1042.  
  1043.  
  1044.  
  1045.  
  1046.  
  1047.  
  1048.  
  1049.                                                                             15
  1050.  
  1051.  
  1052. strings  in  order  to  recognize  the  nesting structure. As puma is oriented
  1053. towards abstract trees, the transformers are independent of parsing or unpars-
  1054. ing.  Besides tree modifications puma allows for tree mappings producing arbi-
  1055. trary output.  Another difference is the explicit  control  of  the  execution
  1056. order which allows an efficient implementation of the generated transformers.
  1057.  
  1058. 6.  Experiences
  1059.  
  1060. In a first real world application, puma was successfully used  to  generate  a
  1061. code-generator  in a compiler for the robot control language IRL [IRL92].  The
  1062. front-end of this  compiler  constructs  an  abstract  syntax  tree  which  is
  1063. decorated  with  attributes  during  the  semantic  analysis  phase. The code-
  1064. generator maps this attributed tree to the  standardized  robot  control  code
  1065. IRDATA [IRD91] which is comparable to assembly code. The strongly typed nature
  1066. of IRDATA makes code-generation harder than one would expect. For instance  it
  1067. is  impossible to implement record variables other than by turning every field
  1068. into a separate variable. More complex types such as arrays with elements of a
  1069. record  type have to be transformed into records containing arrays.  Neverthe-
  1070. less these nontrivial problems could be solved relatively easy with  appropri-
  1071. ate transformation rules.  The code-generator uses a two phase scheme in order
  1072. to deal with forward references.  The first phase selects IRDATA  instructions
  1073. and  stores them in memory. The second phase replaces symbolic labels by abso-
  1074. lute ones, encodes the instructions, and writes the final code  to  an  output
  1075. file.  The data structure for storing the instructions in memory is managed by
  1076. a module generated by the tool ast.  The development time was three months.
  1077.  
  1078.                   Table 1: Sizes of the Code-Generator Parts
  1079.  
  1080.        ____________________________________________________________________
  1081.                                      Specification   C Code    Binary Code
  1082.                                         [lines]      [lines]      [KB]
  1083.        ____________________________________________________________________
  1084.         code selection (puma)            3032          8600        111
  1085.         instruction storage (ast)         165          3430         36
  1086.         output (hand-written)              -            700          7
  1087.        ____________________________________________________________________
  1088.         total                            3197         12730        154
  1089.        ____________________________________________________________________
  1090.       
  1091.  
  1092.  
  1093.  
  1094.  
  1095.  
  1096.                                   
  1097.  
  1098.  
  1099.  
  1100.  
  1101.  
  1102.                                                   
  1103.  
  1104.  
  1105.  
  1106.  
  1107.  
  1108.                                                             
  1109.  
  1110.  
  1111.  
  1112.  
  1113.  
  1114.                                                                           
  1115.  
  1116.  
  1117.  
  1118.  
  1119.  
  1120.  
  1121.  
  1122.  
  1123.  
  1124.      The parts of the code-generator have the sizes listed in  Table  1.   The
  1125. figures  stem from measurements on a SPARC station ELC.  The complete compiler
  1126. runs at speed of 1000 lines per second.  The run time is distributed among the
  1127. phases  as  follows:  Scanning and parsing takes 21 %, semantic analysis 10 %,
  1128. code-generation 18 %, and output of the generated code 51 %.  The  huge  share
  1129. for  the output comes from the voluminous nature of IRDATA. The output reaches
  1130. four times the size of the source program.
  1131.  
  1132. 7.  Conclusions
  1133.  
  1134. We presented a tool for the transformation of attributed trees  using  pattern
  1135. matching.   It  is  based on the definition, composition, and decomposition of
  1136. trees in combination with recursion and pattern matching for trees as well  as
  1137.  
  1138.  
  1139.  
  1140.  
  1141.  
  1142.  
  1143.  
  1144.  
  1145.  
  1146.  
  1147.                                                                             16
  1148.  
  1149.  
  1150. for  attributes.  It supports the mapping of trees to arbitrary output as well
  1151. as the modification of trees. Moreover it can be used to  construct  attribute
  1152. evaluators.  The  easy  escape  to  an imperative programming language assures
  1153. flexibility and practical usability. The tool has been designed to provide  an
  1154. expressive technique that can be implemented efficiently.
  1155.  
  1156.      The tool puma and its predecessor called Gentle [WGS89]  have  been  used
  1157. successfully  in  several real world projects.  At our institution a front-end
  1158. for a C compiler and a compiler for a functional language have been generated.
  1159. An  industrial  company makes use of it for a language implementation project,
  1160. too. All applications report their satisfaction with this approach  and  rela-
  1161. tive short development times. The interesting question is where does this suc-
  1162. cess come from?  The final paragraphs give the author's subjective opinion.
  1163.  
  1164.      First, there are several aspects that support a  high  level  programming
  1165. style.  The data type tree including operations for composition and decomposi-
  1166. tion replaces the handling of pointers, records, and dynamic  storage  alloca-
  1167. tion.   Pattern matching offers a comfortable kind of case statement.  Once it
  1168. is understood and accepted then recursion seems to be easier to deal with then
  1169. iteration.   The  implicit  declaration  of  variables simplifies coding.  The
  1170. check for the single assignment property catches errors  such  as  missing  or
  1171. multiple  computations.  A concise syntactic notation is probably more profit-
  1172. able than one would imagine.  (Many of the the mentioned arguments  have  con-
  1173. tributed  to  the success of Lisp and Prolog.) The approach supports an incre-
  1174. mental development style: Initially, rules for the most general form are  sup-
  1175. plied  and later rules for special cases are added in order to improve perfor-
  1176. mance.  Furthermore static typing  discovers  many  errors  during  generation
  1177. time.
  1178.  
  1179.      Second, the approach is designed to be very  flexible  and  open.   Every
  1180. combination  of  attribute processing from mere reading and matching of attri-
  1181. butes to complete evaluation can be expressed.  The method allows tree modifi-
  1182. cations  as  well  as  mappings  that  produce arbitrary output.  The explicit
  1183. description of execution order gives full control on side effects.  The escape
  1184. to  imperative  programming and the easy integration with external subroutines
  1185. are essential loopholes.  The tool as well as the generated code are efficient
  1186. and can be used in production projects.  It is probably the combination of all
  1187. the mentioned properties and reasons that we regard this approach to  be  very
  1188. promising.
  1189.  
  1190. References
  1191.  
  1192. [AGT89]
  1193.      A. V. Aho, M. Ganapathi and S. W. K. Tjiang, Code Generation  Using  Tree
  1194.      Matching  and Dynamic Programming, ACM Trans. Prog. Lang. and Systems 11,
  1195.      4 (Oct. 1989), 491-516.
  1196.  
  1197. [BMS80]
  1198.      R.  Burstall,  D.  MacQueen  and  D.  Sannella,  HOPE:  An   Experimental
  1199.      Applicative  Language,  Report  CSR-62-80,  Computer  Science Department,
  1200.      Edinburgh, 1980.
  1201.  
  1202.  
  1203.  
  1204.  
  1205.  
  1206.  
  1207.  
  1208.  
  1209.  
  1210.  
  1211.  
  1212.                                                                             17
  1213.  
  1214.  
  1215. [CaC91]
  1216.      I. H. Carmichael and J. R. Cordy, TXL  -  Tree  Transformation  Language,
  1217.      Syntax  and  Informal  Semantics,  Dept.  of  Computing  and  Information
  1218.      Sciences, Queens's Univeristy, Kingston, Apr. 1991.
  1219.  
  1220. [ClM84]
  1221.      W. F. Clocksin and C. S. Mellish, Programming in Prolog, Springer Verlag,
  1222.      Berlin, 1984.
  1223.  
  1224. [CoP90]
  1225.      J. R. Cordy and  E.  Promislow,  Specification  and  Automatic  Prototype
  1226.      Implementation  of  Polymorphic  Objects  in TURING using the TXL Dialect
  1227.      Processor,  Proc.  IEEE  1990  International   Conference   on   Computer
  1228.      Languages, New Orleans, Mar. 1990, 145-154.
  1229.  
  1230. [ESL89]
  1231.      H. Emmelmann, F. W. Schroer and  R.  Landwehr,  BEG  -  a  Generator  for
  1232.      Efficient Back Ends, SIGPLAN Notices 24, 7 (July 1989), 227-237.
  1233.  
  1234. [Gro89]
  1235.      J. Grosch, Ag - An Attribute  Evaluator  Generator,  Compiler  Generation
  1236.      Report  No.  16,  GMD Forschungsstelle an der Universitat Karlsruhe, Aug.
  1237.      1989.
  1238.  
  1239. [GrE90]
  1240.      J. Grosch and H. Emmelmann, A Tool Box for  Compiler  Construction,  LNCS
  1241.      477, (Oct. 1990), 106-116, Springer Verlag.
  1242.  
  1243. [Gro91a]
  1244.      J. Grosch, Puma - A Generator for the Transformation of Attributed Trees,
  1245.      Compiler   Generation   Report   No.  26,  GMD  Forschungsstelle  an  der
  1246.      Universitat Karlsruhe, July 1991.
  1247.  
  1248. [Gro91b]
  1249.      J. Grosch, Tool Support for Data Structures, Structured  Programming  12,
  1250.      (1991), 31-38.
  1251.  
  1252. [HeS91]
  1253.      R. Heckmann and G. Sander, Trafola-H Reference Manual, Prospectra Project
  1254.      Report, Universitat des Saarlandes, Saarbrucken, 1991.
  1255.  
  1256. [IRD91]
  1257.      IRDATA, Industrial Robot Data, DIN 66313, Beuth-Verlag, Berlin, 1991.
  1258.  
  1259. [IRL92]
  1260.      IRL, Industrial Robot  Language,  DIN  66312,  Beuth-Verlag,  Berlin,  to
  1261.      appear, 1992.
  1262.  
  1263. [JoP90]
  1264.      M. Jourdan  and  D.  Parigot,  Application  Development  with  the  FNC-2
  1265.      Attribute Grammar System, LNCS 477, (Oct. 1990), 11-25, Springer Verlag.
  1266.  
  1267.  
  1268.  
  1269.  
  1270.  
  1271.  
  1272.  
  1273.  
  1274.  
  1275.  
  1276.  
  1277.                                                                             18
  1278.  
  1279.  
  1280. [KHZ82]
  1281.      U. Kastens,  B.  Hutt  and  E.  Zimmermann,  GAG:  A  Practical  Compiler
  1282.      Generator, Springer Verlag, Heidelberg, 1982.
  1283.  
  1284. [Knu68]
  1285.      D. E. Knuth, Semantics of Context-Free  Languages,  Mathematical  Systems
  1286.      Theory 2, 2 (June 1968), 127-146.
  1287.  
  1288. [Knu71]
  1289.      D.  E.  Knuth,   Semantics   of   Context-free   Languages:   Correction,
  1290.      Mathematical Systems Theory 5, (Mar. 1971), 95-96.
  1291.  
  1292. [Kos71]
  1293.      C. H. A. Koster, Affix Grammars, in ALGOL 68  Implementation,  J.  E.  L.
  1294.      Peck (ed.), North Holland, Amsterdam, 1971, 95-109.
  1295.  
  1296. [Kos77]
  1297.      C. H. A. Koster,  CDL:  A  Compiler  Implementation  Language,  LNCS  47,
  1298.      (1977), 341-351, Springer Verlag.
  1299.  
  1300. [LMO88]
  1301.      P. Lipps, U. Moncke, M. Olk and R. Wilhelm, Attribute  (Re)evaluation  in
  1302.      OPTRAN, Acta Inf. 26, (1988), 213-239.
  1303.  
  1304. [LMW89]
  1305.      P. Lipps, U. Moncke and R. Wilhelm, OPTRAN - A  Language/System  for  the
  1306.      Specification   of   Program   Transformations,   System   Overview   and
  1307.      Experiences, LNCS 371, (1989), 52-65, Springer Verlag.
  1308.  
  1309. [MAE65]
  1310.      J. McCarthy, P. W. Abrahams, D. J. Edwards, T. R. Hart and M.  I.  Levin,
  1311.      Lisp 1.5 Programmer's Manual, MIT Press, Cambridge, MA, 1965.
  1312.  
  1313. [Mil85]
  1314.      R. Milner, The Standard ML Core Language, Polymorphism 2, 2 (1985), .
  1315.  
  1316. [NAJ76]
  1317.      K. V. Nori, U. Ammann, K.  Jensen,  H.  H.  Nageli  and  C.  Jacobi,  The
  1318.      Pascal-P  Compiler:  Implementation  Notes,  Bericht  10,  Eidgenossische
  1319.      Technische Hochschule, Zurich, July 1976.
  1320.  
  1321. [Paa89]
  1322.      J. Paakki, A Prolog-Based Compiler Writing Tool, in  Proceedings  of  the
  1323.      Workshop  on  Compiler  Compiler  and  High  Speed Compilation, D. Hammer
  1324.      (ed.), Berlin, GDR, 1989, 107-117.
  1325.  
  1326. [Tur85]
  1327.      D. A. Turner, Miranda: A Nonstrict Functional Language  with  Polymorphic
  1328.      Types, LNCS 201, (1985), 1-16, Springer Verlag.
  1329.  
  1330. [Vol91]
  1331.      J. Vollmer, The Compiler Construction  System  GENTLE,  GMD-Arbeitspapier
  1332.      Nr. 508, GMD Forschungsstelle an der Universitat Karlsruhe, Feb. 1991.
  1333.  
  1334.  
  1335.  
  1336.  
  1337.  
  1338.  
  1339.  
  1340.  
  1341.  
  1342.  
  1343.                                                                             19
  1344.  
  1345.  
  1346. [WGS89]
  1347.      W. M. Waite, J. Grosch and F. W. Schroer, Three Compiler  Specifications,
  1348.      GMD-Studie  Nr.  166,  GMD Forschungsstelle an der Universitat Karlsruhe,
  1349.      Aug. 1989.
  1350.  
  1351. [Wat74]
  1352.      D. A.  Watt,  Analysis  Oriented  Two  Level  Grammars,  Ph.  D.  thesis,
  1353.      University of Glasgow, Glasgow, 1974.
  1354.  
  1355.  
  1356.  
  1357.  
  1358.  
  1359.  
  1360.  
  1361.  
  1362.  
  1363.  
  1364.  
  1365.  
  1366.  
  1367.  
  1368.  
  1369.  
  1370.  
  1371.  
  1372.  
  1373.  
  1374.  
  1375.  
  1376.  
  1377.  
  1378.  
  1379.  
  1380.  
  1381.  
  1382.  
  1383.  
  1384.  
  1385.  
  1386.  
  1387.  
  1388.  
  1389.  
  1390.  
  1391.  
  1392.  
  1393.  
  1394.  
  1395.  
  1396.  
  1397.  
  1398.  
  1399.  
  1400.  
  1401.  
  1402.  
  1403.  
  1404.  
  1405.  
  1406.  
  1407.  
  1408.                                                                              1
  1409.  
  1410.  
  1411. Contents
  1412.  
  1413.         Abstract ........................................................    1
  1414.         Keywords ........................................................    1
  1415. 1.      Introduction ....................................................    1
  1416. 2.      Tree Transformation by Pattern Matching .........................    3
  1417. 3.      Specification Language ..........................................    6
  1418. 3.1.    Tree Structure ..................................................    6
  1419. 3.2.    Subroutines .....................................................    7
  1420. 3.3.    Types ...........................................................    8
  1421. 3.4.    Rules ...........................................................    8
  1422. 3.5.    Patterns ........................................................    9
  1423. 3.6.    Expressions .....................................................    9
  1424. 3.7.    Statements ......................................................   10
  1425. 4.      Implementation ..................................................   11
  1426. 5.      Related Research ................................................   12
  1427. 5.1.    Imperative Programming ..........................................   12
  1428. 5.2.    Logic Programming ...............................................   12
  1429. 5.3.    Functional Programming ..........................................   12
  1430. 5.4.    Attribute Grammars ..............................................   13
  1431. 5.5.    Optran ..........................................................   13
  1432. 5.6.    Trafola .........................................................   14
  1433. 5.7.    Codegenerator-Generators ........................................   14
  1434. 5.8.    Txl .............................................................   14
  1435. 6.      Experiences .....................................................   15
  1436. 7.      Conclusions .....................................................   15
  1437.         References ......................................................   16
  1438.  
  1439.  
  1440.  
  1441.  
  1442.  
  1443.  
  1444.  
  1445.  
  1446.  
  1447.  
  1448.  
  1449.  
  1450.  
  1451.  
  1452.  
  1453.  
  1454.  
  1455.  
  1456.  
  1457.  
  1458.  
  1459.  
  1460.  
  1461.  
  1462.  
  1463.  
  1464.  
  1465.  
  1466.  
  1467.  
  1468.  
  1469.